/*******************************************************************************
 * * Copyright 2012 Impetus Infotech.
 *  *
 *  * Licensed under the Apache License, Version 2.0 (the "License");
 *  * you may not use this file except in compliance with the License.
 *  * You may obtain a copy of the License at
 *  *
 *  *      http://www.apache.org/licenses/LICENSE-2.0
 *  *
 *  * Unless required by applicable law or agreed to in writing, software
 *  * distributed under the License is distributed on an "AS IS" BASIS,
 *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  * See the License for the specific language governing permissions and
 *  * limitations under the License.
 ******************************************************************************/
package cn.ilikes.tools.hbase.jpa.metadatas.processor.processores;

import java.lang.reflect.Field;
import java.util.Arrays;

import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;

import org.slf4j.Logger;

import cn.ilikes.tools.hbase.jpa.JPAHBaseRuntimeException;
import cn.ilikes.tools.hbase.jpa.metadatas.EntityMetaDataImpl;
import cn.ilikes.tools.hbase.jpa.metadatas.IEntityMetaData;
import cn.ilikes.tools.hbase.jpa.metadatas.elements.EntityFields;
import cn.ilikes.tools.hbase.jpa.metadatas.elements.EntityFieldsImpl;
import cn.ilikes.tools.hbase.jpa.metadatas.elements.JPAFieldImpl;
import cn.ilikes.tools.hbase.jpa.metadatas.elements.Relation;
import cn.ilikes.tools.hbase.jpa.metadatas.processor.validators.EntityValidatorException;
import cn.ilikes.tools.logs.Loggerfactory;
import cn.ilikes.tools.untils.PropertyAccessorHelper;

public class OneToManyRelationProcessor implements Processors {
	private static Logger logger = Loggerfactory.instance(OneToManyRelationProcessor.class);

	@Override
	public void validators(Class<?> clazz, IEntityMetaData metadata) throws EntityValidatorException {

	}

	@Override
	public void processors(Class<?> clazz, IEntityMetaData metadata) throws ElementProcessorException {
		validators(clazz, metadata);
		Field[] fields = clazz.getDeclaredFields();

		for (Field field : fields) {

			OneToMany ann = field.getAnnotation(OneToMany.class);
			if (ann == null)
				continue;
			Loggerfactory.info(logger, "processors   OneToMany Relation to   Metadata   " + field.getName() + "  EntityMetadata " + metadata);
			Class<?> targetEntity = PropertyAccessorHelper.getGenericClass(field);

			// now, check annotations
			if (null != ann.targetEntity() && !ann.targetEntity().getSimpleName().equals("void")) {
				targetEntity = ann.targetEntity();
			}

			//validate(targetEntity);

			Relation relation = new Relation(field, targetEntity, field.getType(), ann.fetch(), Arrays.asList(ann.cascade()), Boolean.TRUE, ann.mappedBy(),
					Relation.ForeignKey.ONE_TO_MANY);

			boolean isJoinedByFK = field.isAnnotationPresent(JoinColumn.class);
			boolean isJoinedByTable = field.isAnnotationPresent(JoinTable.class);

			if (isJoinedByFK) {
				JoinColumn joinColumnAnn = field.getAnnotation(JoinColumn.class);
				relation.setJoinColumnName(joinColumnAnn.name());
			} else if (isJoinedByTable) {
				//			JoinTableMetadata jtMetadata = new JoinTableMetadata(relationField);
				//
				//			relation.setRelatedViaJoinTable(true);
				//			relation.setJoinTableMetadata(jtMetadata);
				throw new JPAHBaseRuntimeException("this JoinTable is not work ! ");
			}

			Loggerfactory.info(logger, "EntityMetadata  " + metadata.getEntityClazz().getSimpleName() + "add Relation  : " + relation);
			EntityFieldsImpl entityFields = (EntityFieldsImpl) ((EntityMetaDataImpl) metadata).getEntityField(field.getName());

			if (entityFields.getjPAField() == null) {
				JPAFieldImpl jpaFieldImpl = new JPAFieldImpl();
				jpaFieldImpl.setRelation(relation);
				entityFields.setjPAField(jpaFieldImpl);
			} else {
				if (entityFields.getjPAField().getRelation() != null)
					throw new ElementProcessorException("this entity : " + clazz.getSimpleName() + "  field : [ " + field.getName() + " ]   have  relation : "
							+ entityFields.getjPAField().getRelation().getType() + " ;  but this  set  " + relation.getType());
			}

		}

	}

}
